#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

//描述硬件的可变信息
struct gpio_desc {
	unsigned int group;
	unsigned int num[16];
};

static struct gpio_desc gpio_val[6];

//初始化gpio管脚编号
static void gpio_init (void)
{
	int i, j;
	for (i = 0; i < 6; i++) {
		gpio_val[i].group = i;
		for (j = 0; j < 16; j++) {
			gpio_val[i].num[j] = 496 - 16*i + j;
		}
	}
}

//根据组号和组内编号获取数字
static unsigned int gpio_get (struct gpio_desc *gpios, int i)
{
	return gpio_val[gpios[i].group].num[gpios[i].num[0]];
}

//根据用户自己的需求配置节点文件下的属性文件
static int gpio_write (char *pptr, char *attr, char *val)
{
	int fd, len;
	char file_path[256];
	//file_path: /sys/class/gpio/gpio497/attr(direction/edge...)
	sprintf (file_path, "%s/%s", pptr, attr);
	if (0 > (fd = open (file_path, O_WRONLY)))
	{
		perror ("open file_path error!");
		return -1;
	}
	len = strlen (val);
	if (len != write (fd, val, len)) {
		perror ("write val error!");
		close (fd);
		return -1;
	}
	close (fd);
	return 0;
}

int main (int argc, char **argv)
{
	int i = 0;
	char pptr[128];
	struct gpio_desc gpios[4];
	int fd;
	char gpio[4];
	int len;

	//初始化gpio管脚 
	gpio_init ();

	for (i = 0; i < 4; i++) {
		if (i == 0) {
			gpios[0].group = 4;
			gpios[0].num[0] = 11;
		} else {
			gpios[i].group = 5;
			gpios[i].num[0] = 11 + i;
		}
	}

	for (i = 0; i < 4; i++) {
		//获取gpio管脚对应的管脚编号
		//将gpio管脚的设备节点文件的路径保存到pptr
		memset (pptr, 0, sizeof(pptr)/sizeof(char));
		sprintf (pptr, "/sys/class/gpio/gpio%d", gpio_get(gpios, i));
		//判断文件是否存在 
		if (access (pptr, F_OK)) {
			if (0 > (fd = open ("/sys/class/gpio/export", O_WRONLY))){
				perror ("open error");
				exit (-1);
			}
			//将gpio管脚编号转换为字符串
			sprintf (gpio, "%d", gpio_get(gpios, i));
			len = strlen (gpio);

			if (len != write (fd, gpio, len)) {
				perror ("write error");
				close (fd);
				exit (-1);
			}
			close (fd);
		}
		//edge文件
		if (0 > (gpio_write (pptr, "edge", "none"))){
			fprintf (stderr, "config edge attr failed!\n");
			exit (-1);
		}
		//direction文件
		if (0 > (gpio_write (pptr, "direction", "out"))){
			fprintf (stderr, "config direc attr failed!\n");
			exit (-1);
		}
		//让管脚默认输出低电平
		if (0 > (gpio_write (pptr, "value", "0"))){
			fprintf (stderr, "config direc attr failed!\n");
			exit (-1);
		}
	}
	while (1) {
		for (i = 3; i >= 0; i--) {
			memset (pptr, 0, sizeof(pptr)/sizeof(char));
			sprintf (pptr, "/sys/class/gpio/gpio%d", gpio_get(gpios, i));
			gpio_write (pptr, "value", "1");
			usleep (10000);
			gpio_write (pptr, "value", "0");
		}
	}

	return 0;
}
